package me.szlx.validation;

import me.szlx.validation.namespace.NameSpace;
import me.szlx.validation.system.ConstraintSystem;

/**
 * 有条件的出错约束。一般地，当条件成立时，则出错。
 */
public interface Validator {
    /**
     * 获取校验的约束。
     *
     * @return 校验的约束。
     */
    Constraint getConstraint();

    /**
     * 立即抛出当前约束的异常。
     */
    default void invalid() {
        ConstraintSystem.get().getInvalidationHandler().handle(getConstraint());
    }

    /**
     * 立即抛出当前约束的异常。
     *
     * @param nameSpace 使用约束时所处的名称空间。
     */
    default void invalid(NameSpace nameSpace) {
        String constraintCode = nameSpace.decorate(getConstraint().code());
        Constraint constraint = nameSpace != null ? Constraint.of(constraintCode) : getConstraint();
        ConstraintSystem.get().getInvalidationHandler().handle(constraint);
    }

    /**
     * 立即抛出当前约束的异常。
     *
     * @param cause 导致约束触发异常的原因。
     */
    default void invalid(Throwable cause) {
        ConstraintSystem.get().getInvalidationHandler().handle(getConstraint(), cause);
    }

    /**
     * 立即抛出当前约束的异常。
     *
     * @param nameSpace 使用约束时所处的名称空间。
     * @param cause     导致约束触发异常的原因。
     */
    default void invalid(NameSpace nameSpace, Throwable cause) {
        String constraintCode = nameSpace.decorate(getConstraint().code());
        Constraint constraint = nameSpace != null ? Constraint.of(constraintCode) : getConstraint();
        ConstraintSystem.get().getInvalidationHandler().handle(constraint, cause);
    }

    /**
     * 根据条件触发异常或设什么也不做。
     *
     * @param predicate 触发约束条件。如果为 {code true}， 则触发约束，否则舍什么也不做。
     */
    default void invalidIf(boolean predicate) {
        if (predicate) {
            ConstraintSystem.get().getInvalidationHandler().handle(getConstraint());
        }
    }

    /**
     * 根据条件触发异常或设什么也不做。
     *
     * @param predicate 触发约束条件。如果为 {code true}， 则触发约束，否则什么也不做。
     * @param nameSpace 约束使用时所处的名称空间。
     */
    default void invalidIf(boolean predicate, NameSpace nameSpace) {
        if (predicate) {
            String constraintCode = nameSpace.decorate(getConstraint().code());
            Constraint constraint = nameSpace != null ? Constraint.of(constraintCode) : getConstraint();
            ConstraintSystem.get().getInvalidationHandler().handle(constraint);
        }
    }

    /**
     * 根据条件触发异常或设什么也不做。
     *
     * @param conditional 触发约束条件。如果条件应用结果为 {code true}， 则触发约束，否则什么也不做。
     */
    default void invalidIf(Conditional conditional) {
        Assert.notNull(conditional, "约束条件不能为null");
        invalidIf(conditional.apply());
    }

    /**
     * 根据条件触发异常或设什么也不做。
     *
     * @param conditional 触发约束条件。如果条件应用结果为 {code true}， 则触发约束，否则什么也不做。
     * @param nameSpace   约束使用时所处的名称空间。
     */
    default void invalidIf(Conditional conditional, NameSpace nameSpace) {
        Assert.notNull(conditional, "约束条件不能为null");
        invalidIf(conditional.apply(), nameSpace);
    }
}
